package com.am.server.api.system.upload.service.impl;

import cn.hutool.core.io.file.PathUtil;
import cn.hutool.core.text.CharSequenceUtil;
import com.am.server.api.system.upload.config.LocalFileUploadConfig;
import com.am.server.api.system.upload.dao.rdb.SysFileDao;
import com.am.server.api.system.upload.enumerate.FileType;
import com.am.server.api.system.upload.exception.DeleteFileException;
import com.am.server.api.system.upload.model.dto.UploadResultDto;
import com.am.server.api.system.upload.model.entity.SysFileEntity;
import com.am.server.api.system.upload.service.FileUploadService;
import com.am.server.api.system.upload.service.SysFileService;
import com.am.server.common.annotation.transaction.Commit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;

/**
 * @author 阮雪峰
 */
@Slf4j
@Service
public class SysFileServiceImpl implements SysFileService {
    /**
     * 默认文件名后缀
     */
    private static final String DEFAULT_FILE_SUFFIX = "jpg";

    private final FileUploadService fileUploadService;
    private final SysFileDao sysFileDao;
    private final LocalFileUploadConfig localFileUploadConfig;

    public SysFileServiceImpl(FileUploadService fileUploadService, SysFileDao sysFileDao, LocalFileUploadConfig localFileUploadConfig) {
        this.fileUploadService = fileUploadService;
        this.sysFileDao = sysFileDao;
        this.localFileUploadConfig = localFileUploadConfig;
    }

    @Commit
    @Override
    public UploadResultDto save(MultipartFile file, FileType type) {
        SysFileEntity fileEntity = new SysFileEntity();
        sysFileDao.save(fileEntity);
        //获取文件后缀名
        String suffix = CharSequenceUtil.isNotEmpty(file.getOriginalFilename()) ? CharSequenceUtil.subAfter(file.getOriginalFilename(), ".", true) : DEFAULT_FILE_SUFFIX;
        String key = type.getFolder() + File.separator + fileEntity.getId() + "." + suffix;
        String url = fileUploadService.upload(file, key);

        fileEntity.setFileName(file.getOriginalFilename());
        fileEntity.setType(type);
        fileEntity.setDir(key);
        fileEntity.setUrl(url);

        return new UploadResultDto(fileEntity.getId(), url);
    }

    @Commit
    @Override
    public String updateFileContent(MultipartFile file, SysFileEntity sysFile, FileType fileType) {
        if (sysFile == null) {
            return save(file, fileType).getUrl();
        }
        String url = fileUploadService.upload(file, sysFile.getDir());
        sysFile.setUrl(url);

        return url;
    }

    @Commit
    @Override
    public void remove(SysFileEntity entity) {
        try {
            Path path = Path.of(localFileUploadConfig.getFilePath() + entity.getDir());
            if (PathUtil.exists(path, Boolean.FALSE)) {
                // 如果存在文件则删除
                Files.delete(path);
            }
            sysFileDao.delete(entity);
        } catch (IOException e) {
            log.error(String.format("删除文件%s(%s)发生异常", entity.getFileName(), entity.getId()), e);
            throw new DeleteFileException(String.format("删除文件%s发生异常", entity.getFileName()), e);
        }
    }

    @Commit
    @Override
    public void remove(Long id) {
        sysFileDao.findById(id).ifPresent(this::remove);
    }

    @Commit
    @Override
    public void removeAll(List<SysFileEntity> entities) {
        SysFileEntity entity = null;
        try {
            for (SysFileEntity item : entities) {
                entity = item;
                Path path = Path.of(localFileUploadConfig.getFilePath() + entity.getDir());
                if (PathUtil.exists(path, Boolean.FALSE)) {
                    // 如果存在文件则删除
                    Files.delete(path);
                }
            }
            sysFileDao.deleteAll(entities);
        } catch (IOException e) {
            Objects.requireNonNull(entity);
            log.error(String.format("删除文件%s(%s)发生异常", entity.getFileName(), entity.getId()), e);
            throw new DeleteFileException(String.format("删除文件%s发生异常", entity.getFileName()), e);
        }
    }

    @Override
    public SysFileEntity findById(Long id) {
        return sysFileDao.findById(id).orElse(new SysFileEntity());
    }
}
